package com.paper.tiger.datasource.config;

import com.paper.tiger.datasource.aop.DataSourceAnnotionAdvisor;
import com.paper.tiger.datasource.aop.DataSourceAnnotionMethodIntercept;
import com.paper.tiger.datasource.common.DataSourceConfig;
import com.paper.tiger.datasource.common.DataSourceConfigProperties;
import com.paper.tiger.datasource.common.DynamicDataSource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * [简要描述]:
 * [详细描述]:
 *
 * @author ZouHaiBo
 * @version 1.0, 2021/5/19 11:23
 * @since JDK 1.8
 */
@Configuration
@AutoConfigureBefore(value = DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(value = DataSourceConfigProperties.class)
public class MultipartDataSourceAutoConfiguration implements InitializingBean
{

    private static final Logger log = LoggerFactory.getLogger(MultipartDataSourceAutoConfiguration.class);


    @Autowired
    private DataSourceConfigProperties dataSourceConfigProperties;

    private DataSource defaultDataSource;

    private Map<Object, Object> targetDataSources = new HashMap<>();

    @Override
    public void afterPropertiesSet()
    {
        // 记载数据源配置，创建对应的数据源
        Map<String, DataSourceConfig> source = dataSourceConfigProperties.getSource();
        source.forEach((sourceName,sourceConfig)->{

            HikariConfig config = new HikariConfig();
            config.setUsername(sourceConfig.getUsername());
            config.setPassword(sourceConfig.getPassword());
            config.setJdbcUrl(sourceConfig.getUrl());
            config.setDriverClassName(sourceConfig.getDriver());
            config.setPoolName(sourceName+"PoolName");
            HikariDataSource dataSource = new HikariDataSource(config);
            if (sourceName.equals("master")){
               setDefaultDataSource(dataSource);
            }

            targetDataSources.put(sourceName,dataSource);

        });
    }

    @Bean
    @ConditionalOnMissingBean
    @Primary
    public DynamicDataSource dynamicDataSource()
    {
        log.info("开始创建动态数据源,创建参数为：defaultDataSource:{},targetDataSources:{}",defaultDataSource,targetDataSources);
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }
    @Bean
    @ConditionalOnMissingBean
    public DataSourceAnnotionMethodIntercept dataSourceAnnotionMethodIntercept() {
        DataSourceAnnotionMethodIntercept intercept = new DataSourceAnnotionMethodIntercept();
        return intercept;
    }

    @Bean
    @ConditionalOnMissingBean
    public DataSourceAnnotionAdvisor dataSourceAnnotionAdvisor(@Autowired DataSourceAnnotionMethodIntercept dataSourceAnnotionMethodIntercept) {
        DataSourceAnnotionAdvisor annotionAdvisor = new DataSourceAnnotionAdvisor(dataSourceAnnotionMethodIntercept);
        return annotionAdvisor;
    }

    public Map<Object, Object> getTargetDataSources()
    {
        return targetDataSources;
    }

    public void setTargetDataSources(Map<Object, Object> targetDataSources)
    {
        this.targetDataSources = targetDataSources;
    }

    public DataSource getDefaultDataSource()
    {
        return defaultDataSource;
    }

    public void setDefaultDataSource(DataSource defaultDataSource)
    {
        this.defaultDataSource = defaultDataSource;
    }


}
